package com.zx.mes.upms.hyl.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zx.mes.hyl.controller.BaseMethod;
import com.zx.mes.hyl.pagemodel.PageParam;
import com.zx.mes.hyl.response.ObjectRestResponse;
import com.zx.mes.hyl.response.TableResultResponse;
import com.zx.mes.upms.hyl.entity.*;
import com.zx.mes.upms.hyl.pagemodel.LoginAppUser;
import com.zx.mes.upms.hyl.service.*;
import com.zx.mes.upms.hyl.util.AppUserUtil;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author 华云龙
 * @since 2019-02-15
 */
@RestController
@RequestMapping("/user")
public class UserController extends BaseMethod<UserService, User> {

    @Autowired
    private RoleUserService sysRoleUserService;

    @Autowired
    private RoleService sysRoleService;

    @Autowired
    private RolePermissionService sysRolePermissionService;

    @Autowired
    private PermissionService sysPermissionService;

    @Autowired
    private UserCredentialsService userCredentialsService;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    /**
     * 使用要求:所有的表都必需有唯一key值,且名称为 REFLECTION_FIELD_NAME (id)
     *
     * @param entity 实体类(pojo)
     * @return ObjectRestResponse
     */
    @PreAuthorize("hasAuthority('back:user:save')")
    @ApiOperation(value = "添加一笔数据", notes = "根据id自生成(数据库),还是前端生成(自身成36位)")
    @PostMapping(value = "/add")
    public ObjectRestResponse<User> save(@RequestBody User entity) {
        entity.setId(baseControllerExt.getUUID())
                .setCreateTime(LocalDateTime.now()).setUpdateTime(LocalDateTime.now());
        return super.add(entity);
    }

    @PreAuthorize("hasAuthority('back:user:query')")
    @ApiOperation(value = "根据所传id(数据库表的主键必需是id才能用)")
    @GetMapping(value = "getOne/{id}")
    public ObjectRestResponse<User> getById(@ApiParam("id 是数据库的唯一主键") @PathVariable String id) {
        return super.get(id);
    }

    /**
     * {
     * "status": 200,
     * "message": "数据更新成功!",
     * "data": null,
     * "rel": true
     * }
     *
     * @param entity 对应实体类
     * @return ObjectRestResponse
     */
    @PreAuthorize("hasAuthority('back:user:update')")
    @ApiOperation(value = "单笔更新操作", notes = "必需根据id来更新")
    @PutMapping(value = "update")
    public ObjectRestResponse<User> updateByEntity(@RequestBody User entity) {
        entity.setUpdateTime(LocalDateTime.now());
        return super.update(entity);
    }

    @PreAuthorize("hasAuthority('back:user:delete')")
    @ApiOperation(value = "单笔删除操作", notes = "必需根据id来删除")
    @DeleteMapping(value = "delete/{id}")
    public ObjectRestResponse<User> del(@PathVariable String id) {
        return super.remove(id);
    }

    @PreAuthorize("hasAuthority('back:user:query')")
    @ApiOperation(value = "获取所有的数据", notes = "一般不推荐使用,小数据量可以")
    @GetMapping(value = "/all")
    public List<User> getAll() {
        return super.all();
    }

    @PreAuthorize("hasAuthority('back:user:page')")
    @ApiOperation(value = "分页操作", notes = "params HashMap example = \"page=1&limit=5\"")
    @SuppressWarnings({"unchecked"})
    @GetMapping(value = "/page")
    public TableResultResponse page(@RequestParam Map<String, Object> params, User entity) {
        TableResultResponse.Builder<User> builder = new TableResultResponse.Builder();
        PageParam extPageParams = this.baseControllerExt.getPageParams(params);
        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
        /// username like
        if (entity != null && StringUtils.isNotBlank(entity.getUsername())) {
            lambda.like(User::getUsername, entity.getUsername());
        }
        /// nickName like
        if (entity != null && StringUtils.isNotBlank(entity.getNickname())) {
            lambda.like(User::getNickname, entity.getNickname());
        }

        List<User> list = this.biz.page(new Page((long) extPageParams.getPage(), (long) extPageParams.getLimit()), lambda).getRecords();
        if (null != list && list.size() != 0) {
            builder.message("分页查询结果").total((long) list.size()).total((long) this.biz.count(null)).page((long) extPageParams.getPage()).rows(list);
        } else {
            builder.message("无数据").page(0L).rows(null);
        }

        return builder.build();
    }

    @PreAuthorize("hasAuthority('back:user:del')")
    @DeleteMapping(value = "/deleteBatch")
    public ObjectRestResponse<User> deleteBatch(@RequestParam String ids) {
        ObjectRestResponse.Builder<User> response = new ObjectRestResponse.Builder<>();
        /// 删除用户时,中间表对应的关系也应删除
        /// 参数检查
        if (StringUtils.isNotBlank(ids)) {
            List<String> list = this.baseControllerExt.divideStrToList(ids);
            /// 1.删除用户-角色中间表关系
            this.sysRoleUserService.remove(new QueryWrapper<RoleUser>().lambda().in(RoleUser::getUserId, list));
            /// 2.删除 用户凭证中对应用户的数据
            this.userCredentialsService.remove(new QueryWrapper<UserCredentials>().lambda().in(UserCredentials::getUserId, list));
            /// 3.删除用户本身数据
            this.biz.removeByIds(list);
            response.message("批量删除成功!");
        } else {
            response.message("所传参数无效,请检查!");
        }
        return response.build();
    }

    @GetMapping(value = "/users-anon/internal", params = "username")
    public LoginAppUser findByUsername(String username) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getUsername, username);
        User appUser = this.biz.getOne(wrapper);
        LoginAppUser loginAppUser = new LoginAppUser();

        if (appUser != null) {
            /// 用户信息赋值
            BeanUtils.copyProperties(appUser, loginAppUser);
            List<RoleUser> sysRoleUsers = this.sysRoleUserService.list(new QueryWrapper<RoleUser>()
                    .lambda().eq(RoleUser::getUserId, appUser.getId()));
            List<String> roleIdList = new ArrayList<>();
            for (int i = 0; i < sysRoleUsers.size(); i++) {
                roleIdList.add(sysRoleUsers.get(i).getRoleId());
            }

            /// 这个人是否有角色
            if (roleIdList.size() > 0) {
                List<Role> sysRoles = this.sysRoleService.list(new QueryWrapper<Role>().lambda().in(Role::getId, roleIdList));
                /// 角色赋值
                loginAppUser.setSysRoles(new HashSet<>(sysRoles));

                List<RolePermission> sysRolePermissions = this.sysRolePermissionService.list(new QueryWrapper<RolePermission>().lambda().in(RolePermission::getRoleId, roleIdList));

                /// 这个角色是否有权限
                if (sysRolePermissions.size() > 0) {
                    List<String> permissionIdList = new ArrayList<>();
                    for (int i = 0; i < sysRolePermissions.size(); i++) {
                        permissionIdList.add(sysRolePermissions.get(i).getPermissionId());
                    }
                    List<Permission> sysPermissionList = this.sysPermissionService.list(new QueryWrapper<Permission>().lambda().in(Permission::getId, permissionIdList));
                    Set<String> permissions = new HashSet<>();
                    for (int i = 0; i < sysPermissionList.size(); i++) {
                        permissions.add(sysPermissionList.get(i).getPermission());
                    }
                    /// 权限赋值
                    loginAppUser.setPermissions(permissions);
                }
            }
        }

        return loginAppUser;
    }

    /**
     * 当前登录用户 LoginAppUser
     */
    @GetMapping("/current")
    public ObjectRestResponse<LoginAppUser> getLoginAppUser() {
        ObjectRestResponse.Builder<LoginAppUser> response = new ObjectRestResponse.Builder<>();
        response.data(AppUserUtil.getLoginAppUser()).message("获取详细的用户信息成功!");
        return response.build();
    }


    /**
     * 用户授权角色
     *
     * @param appUser 用户
     * @return response
     */
    @PostMapping("/grantRole")
    public ObjectRestResponse<User> grantRole(@RequestBody User appUser) {
        ObjectRestResponse.Builder<User> response = new ObjectRestResponse.Builder<>();
        /// 最直接的就是 1.先删除原来所有的角色,2.再将新的角色授权给用户

        /// 1.删除中间表中所有与userId相关的数据
        this.sysRoleUserService.remove(new QueryWrapper<RoleUser>().lambda().eq(RoleUser::getUserId, appUser.getUserId()));
        /// 2.解析要授权的角色,再插入中间表
        List<String> list = this.baseControllerExt.divideStrToList(appUser.getRoleIds());
        List<RoleUser> roleUserList = new ArrayList<>(8);
        list.forEach(item -> {
            RoleUser sysRoleUser = new RoleUser();
            sysRoleUser.setUserId(appUser.getUserId()).setRoleId(item);
            roleUserList.add(sysRoleUser);
        });
        this.sysRoleUserService.saveBatch(new ArrayList<>(roleUserList));
        response.message("授权成功!");
        return response.build();
    }


    @GetMapping("/getRoleByUserId")
    public ObjectRestResponse<User> getRoleByUserId(String userId) {
        ObjectRestResponse.Builder<User> response = new ObjectRestResponse.Builder<>();
        /// 1.从 角色-用户表中找到对应角色信息
        List<RoleUser> list = this.sysRoleUserService.list(new QueryWrapper<RoleUser>().lambda().eq(RoleUser::getUserId, userId));
        /// 2.从 角色表中获取详细信息
        if (list != null && list.size() > 0) {
            List<String> roleIdList = new ArrayList<>(4);
            list.forEach(item -> roleIdList.add(item.getRoleId()));
            List<Role> sysRoleList = this.sysRoleService.list(new QueryWrapper<Role>().lambda().in(Role::getId, new ArrayList<>(roleIdList)));
            response.message("获取角色成功!").data(sysRoleList);
        } else {
            response.message("未获取到用户角色的相关信息!");
        }
        return response.build();
    }
}

